#include "ring_buffer.h"

/**
 * @description: 创建一个环形缓冲区 根据大小分配内存空间
 * @param {size_t} size 需要分配的缓冲区大小
 * @return {*} 返回一个指向环形缓冲区的指针，如果分配失败则返回NULL
 */
ring_buffer_t *ring_buffer_create(size_t size)
{
    if (size == 0)
    {
        return NULL;
    }

    ring_buffer_t *ring_buffer = (ring_buffer_t *)RING_BUFFER_MALLOC(sizeof(ring_buffer_t));
    if (!ring_buffer)
    {
        return NULL;
    }

    ring_buffer->head = (uint8_t *)RING_BUFFER_MALLOC(size + 1);
    if (!ring_buffer->head)
    {
        RING_BUFFER_FREE(ring_buffer);
        return NULL;
    }

    ring_buffer->tail = ring_buffer->head + size + 1;
    ring_buffer->read = ring_buffer->head;
    ring_buffer->write = ring_buffer->head + 1; // 初始化写指针，预留一个字节以区分满和空
    ring_buffer->max_size = size;               // 实际可用大小为size

    return ring_buffer;
}

/**
 * @description: 删除环形缓冲区并释放内存
 * @param {ring_buffer_t} *ring_buffer 指向需要删除的环形缓冲区
 * @return {*} 返回RING_BUFFER_OK表示成功，其他值表示错误
 */
int ring_buffer_delete(ring_buffer_t *ring_buffer)
{
    if (!ring_buffer)
    {
        return RING_BUFFER_ERROR;
    }

    RING_BUFFER_FREE(ring_buffer->head);
    RING_BUFFER_FREE(ring_buffer);
    return RING_BUFFER_OK;
}

/**
 * @description: 计算环形缓冲区当前可用空间
 * @param {ring_buffer_t} *ring_buffer 一个指向环形缓冲区的指针
 * @return {*} 返回当前可用空间的大小
 */
size_t ring_buffer_available_space(ring_buffer_t *ring_buffer)
{
    if (!ring_buffer)
    {
        return 0;
    }

    // 计算缓冲区当前可用空间
    size_t available_space = ring_buffer->write > ring_buffer->read
                                 ? (ring_buffer->tail - ring_buffer->write) + (ring_buffer->read - ring_buffer->head)
                                 : (ring_buffer->read - ring_buffer->write);
    return available_space;
}

/**
 * @description: 计算环形缓冲区当前可用数据
 * @param {ring_buffer_t} *ring_buffer 一个指向环形缓冲区的指针
 * @return {*} 返回当前可用数据的大小
 */
size_t ring_buffer_available_data(ring_buffer_t *ring_buffer)
{
    if (!ring_buffer)
    {
        return 0;
    }

    // 计算缓冲区当前可用数据
    size_t available_data = ring_buffer->write > ring_buffer->read
                                ? (ring_buffer->write - ring_buffer->read) - 1
                                : (ring_buffer->tail - ring_buffer->read) + (ring_buffer->write - ring_buffer->head) - 1;
    return available_data;
}

/**
 * @description: 写入数据到环形缓冲区
 * @param {ring_buffer_t} *ring_buffer 一个指向环形缓冲区的指针
 * @param {uint8_t} *data 指向要写入的数据的指针
 * @param {size_t} size 要写入的数据大小
 * @return {*}
 */
int ring_buffer_write(ring_buffer_t *ring_buffer, const uint8_t *data, size_t size)
{
    if (!ring_buffer || !data || size == 0 || size > ring_buffer->max_size)
    {
        return RING_BUFFER_ERROR;
    }

    // 计算缓冲区当前可用空间
    size_t available_space = ring_buffer_available_space(ring_buffer);

    // 写入的数据大于当前可用空间
    if (size > available_space)
    {
        return RING_BUFFER_NO_SPACE;
    }

    // 用于保护写入指针 在写入成功后改变结构体中的指针
    uint8_t *write_ptr = ring_buffer->write;

    if (write_ptr == ring_buffer->read)
    {
        return RING_BUFFER_FULL; // 如果写指针和读指针相同，表示缓冲区已满
    }

    for (size_t i = 0; i < size; i++)
    {
        *write_ptr = data[i];
        write_ptr++;

        // 如果写指针到达尾部，则回绕到头部
        if (write_ptr == ring_buffer->tail)
        {
            write_ptr = ring_buffer->head;
        }
    }
    // 更新环形缓冲区的写指针
    ring_buffer->write = write_ptr;

    return RING_BUFFER_OK;
}

/**
 * @description: 从环形缓冲区读取数据
 * @param {ring_buffer_t} *ring_buffer 一个指向环形缓冲区的指针
 * @param {uint8_t} *data 指向存储读取数据的缓冲区的指针
 * @param {size_t} size 要读取的数据大小
 * @return {*}
 */
int ring_buffer_read(ring_buffer_t *ring_buffer, uint8_t *data, size_t size)
{
    if (!ring_buffer || !data || size == 0 || size > ring_buffer->max_size)
    {
        return RING_BUFFER_ERROR;
    }

    // 计算缓冲区当前可用数据
    size_t available_data = ring_buffer_available_data(ring_buffer);

    // 读取的数据大于当前可用数据
    if (size > available_data)
    {
        return RING_BUFFER_READ_INSUFFICIENT;
    }

    // 用于保护读指针 在读取成功后改变结构体中的指针
    uint8_t *read_ptr = ring_buffer->read;

    for (size_t i = 0; i < size; i++)
    {
        read_ptr++;

        // 如果读指针到达尾部，则回绕到头部
        if (read_ptr == ring_buffer->tail)
        {
            read_ptr = ring_buffer->head;
        }
        data[i] = *read_ptr;
    }
    // 更新环形缓冲区的读指针
    ring_buffer->read = read_ptr;

    return RING_BUFFER_OK;
}
